<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Javascript fluid dynamics</title>
<script language="javascript" type="text/javascript" src="fluid.js"></script>
<script language="javascript" type="text/javascript">

var ctx;
var image_data;
var imageTimer;
var fluidTimer;
var iteration = 0;
var iterative_steps = 5;

var hspeed = [];
var vspeed = [];
r = [];
g = [];
b = [];
var imgd;
var size = 100;

var oldx,oldy;
var radius = 100;
dragging = false;

var dt = 1;
var diff = 0;
var visc = 1000;

function toFluid(data, r, g, b)
{
    for (var i=0; i < data.length; i+=4)
    {
        r.push(data[i]);
        g.push(data[i+1]);
        b.push(data[i+2]);
        hspeed.push(0);
        vspeed.push(0);
    }
}

function fromFluid(image_data, r, g, b)
{
    for (var i=0; i < r.length; i++)
    {
        image_data[4*i] = r[i];
        image_data[4*i + 1] = g[i];
        image_data[4*i + 2] = b[i];
        image_data[4*i + 3] = 255;
    }
}

function runImage()
{
    fromFluid(imgd.data, r, g, b);
    ctx.putImageData(imgd,0,0);
    imageTimer = setTimeout(runImage, 40);
}

function runFluid()
{
    iteration++;
    ///////////
        
    compute_speeds( size, hspeed, vspeed, visc, dt );
    compute_densityes( size, r, g, b, hspeed, vspeed, diff, dt );
//    compute_density( size, g, hspeed, vspeed, diff, dt );
//    compute_density( size, b, hspeed, vspeed, diff, dt );
    
    ///////////
    fluidTimer = setTimeout(runFluid, 30);
}

function init()
{
    var img = document.getElementById("fluid_image");
    var canvas = document.getElementById("fluid_canvas");
    canvas.width = img.width;
    canvas.height = img.height;
    size = Math.min( canvas.width, canvas.height);
    
    ctx = canvas.getContext("2d");
    if (0)
        ctx.drawImage(img,0,0);
    else
    {
        var lingrad = ctx.createLinearGradient(0,0,0,canvas.height);
        lingrad.addColorStop(0,'red');  
        lingrad.addColorStop(1,'blue');
        ctx.fillStyle = lingrad;
        ctx.fillRect(0,0,canvas.width,canvas.height);
    }
    try
    {
        imgd = ctx.getImageData(0, 0, canvas.width, canvas.height);
    }
    catch(e)
    {
        try
        {
            netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
        }
        catch(ev){}
        imgd = ctx.getImageData(0, 0, canvas.width, canvas.height);
    }
    toFluid(imgd.data, r, g, b);
    canvas.addEventListener('mousemove', ev_mousemove, false);
    canvas.addEventListener('mousedown', ev_mousedown, false);
    canvas.addEventListener('mouseup', ev_mouseup, false);
    toggle();
}

function ev_mousedown(ev)
{
      dragging = true;
}

function ev_mouseup(ev)
{
    dragging = false;
}

function ev_mousemove(ev)
{
     var x, y;
  // Get the mouse position relative to the canvas element.
  if (ev.layerX || ev.layerX == 0) { // Firefox
    x = ev.layerX;
    y = ev.layerY;
  } else if (ev.offsetX || ev.offsetX == 0) { // Opera
    x = ev.offsetX;
    y = ev.offsetY;
  }
  x = x - ev.target.offsetLeft;
  y = y - ev.target.offsetTop;
  
  //calculate speeds
  var speedx = x - (oldx || x);
  var speedy = y - (oldy || y);
  //update speeds
  if (dragging)
  for (var i = 0; i < size; i++)
    for (var j = 0; j < size; j++)
    {
        var d = (x-i)*(x-i) + (y-j)*(y-j);
        if (d < radius)
        {
            hspeed[ind(i,j)] += speedx/radius;
            vspeed[ind(i,j)] += speedy/radius;
        }
    }

  
  //update old values
  oldx = x;
  oldy = y;
  
  return false;
}

function toggle()
{
    if (fluidTimer || imageTimer)
    {
        clearTimeout(fluidTimer);
        clearTimeout(imageTimer);
        fluidTimer = null;
        imageTimer = null;
    }
    else
    {
        fluidTimer = setTimeout(runFluid,10);
        imageTimer = setTimeout(runImage,10);
    }
}

</script>
</head>
<body onload="init();">
<img id="fluid_image" src="canvas.png"/>
<canvas id="fluid_canvas"></canvas><br />
<button onclick="toggle();">Start/Stop</button><br />
<div id="score"></div>
</body>
</html>